#ifndef PIPE_H
#define PIPE_H

#include "main_inc.h"
#include "exceptions.h"

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501

#include <winsock2.h>
#include <ws2tcpip.h>

#include "FastDelegate.h"

///err_codes:
#define ER_RESOLUTION           0xB001
#define ER_SOCKET_CREATION      0xB002
#define ER_CONNECTING           0xB003
#define ER_SENDING              0xB004
#define ER_RECIVING             0xB005
#define ER_SETTING              0xB006
#define ER_CLOSING              0xB007

#define ST_CLOSED               0xC001
#define ST_CLOSED_BY_ME         0xC002

#define FLAG_S                    0x0F00
///----------
#define RB_SIZE                 4096
class Pipe;
typedef fastdelegate::FastDelegate3<Pipe*,i32,i32,void> callback;

extern u32 pip_p_initialized;

//void *th_connect( void *);

class Pipe
{
public:
    Pipe();
    virtual ~Pipe();
    static int Cleanup();

    i32 Connect(string url, u16 port);
    i32 Close(i32 produce_error = 1);       // if pe flag is 0, will not throw errors when closing non scoket.
    i32 Send(i8 *data, u32 len);
    i32 Recv(i8 **data, u32 &len);
    i32 ClearRecvBuff(u32 len = 0xffffffff);
    i32 IsConnected();
    i32 IsReadyRead();
    callback onConnected;
    callback onError;
    callback onReadyRead;
    callback onDataSent;

    i32 user_data;

    void setSocket( int socket )
    {
        p_socket = socket;
    }
    i32 startReading()
    {
        _only_read = 1;
        Connect("",0);
        return 0;
    }


protected:

    int pInit();
    void p_error( int err_code, string err = "");

protected:

    pthread_t p_thr_connect;//p_thr_send;
public:
    pthread_mutex_t p_mx_brecv;
    vector<i8> p_buff_recv;
    int _only_read;
protected:
    int p_socket;

//    u32 fl_connecting : 1;
//    u32 fl_connected : 1;
//    u32 fl_idle : 1;
//    u32 fl_error : 1;
//    u32 fl_readyread : 1;

protected:

    string p_url;
    u16 p_port;

    hostent *p_srv_info;
    sockaddr_in p_srv_addr;
    addrinfo p_hints;
    addrinfo *p_res;
    sockaddr_storage p_remoteaddr;
    int p_exit_flag;

    static void *th_connect( void *param );

};

#define MX_FLAG_E   ENTER_CS(p_mx_flag)
#define MX_FLAG_L   LEAVE_CS(p_mx_flag)


string ErrToStr ( i32 sys_err );



#endif // PIPE_H
